package com.powerteam.service.crm.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.powerteam.exception.BusinessException;
import com.powerteam.mapper.crm.OpportunityMapper;
import com.powerteam.model.crm.Activity;
import com.powerteam.model.crm.ContactsRole;
import com.powerteam.model.crm.Opportunity;
import com.powerteam.model.crm.ShareGroup;
import com.powerteam.service.crm.ActivityService;
import com.powerteam.service.crm.OpportunityService;
import com.powerteam.service.crm.ShareGroupService;
import com.powerteam.util.DateUtil;
import com.powerteam.vo.Result;
import com.powerteam.vo.crm.QueryOpportunityVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import static com.powerteam.model.enums.ActivityTypeEnum.ACTIVITY_TYPE_SYSTEM_TRACE;
import static com.powerteam.model.enums.ContactsRoleTypeEnum.CONTACTS_ROLE_TYPE_LIAISONS;
import static com.powerteam.model.enums.OpportunityPhaseEnum.*;
import static com.powerteam.model.enums.ResourceTypeEnum.RESOURCE_TYPE_OPPORTUNITY;

/**
 * 机会相关服务接口实现
 *
 * @author jinming.zhang
 * @version 0.0.1
 * @date 2021/12/30
 */
@Slf4j
@Service
public class OpportunityServiceImpl implements OpportunityService {


    private static final String CLASS_NAME = "OpportunityServiceImpl";

    @Autowired
    private OpportunityMapper opportunityMapper;

    @Autowired
    private ShareGroupService shareGroupService;

    @Autowired
    private ActivityService activityService;

    @Override
    @Transactional(rollbackFor = {BusinessException.class}, propagation = Propagation.REQUIRED)
    public Result insert(Opportunity opportunity) {

        opportunity.setPossibility(0f);
        opportunity.setCreateDate(new Date());
        opportunity.setOwner(opportunity.getCreateBy());
        opportunity.setPhase(OPPORTUNITY_PHASE_INITIAL.getCode());

        try {

            // 创建业务机会信息
            if (opportunityMapper.insert(opportunity) > 0) {
                log.info("{} insert 创建业务机会 入参0:{}", CLASS_NAME, JSON.toJSON(opportunity));
                ShareGroup shareGroup = new ShareGroup();
                shareGroup.setResourceType(RESOURCE_TYPE_OPPORTUNITY.getCode());
                shareGroup.setResourceId(opportunity.getOpportunityId());
                shareGroup.setUserId(opportunity.getCreateBy());

                // 创建共享组信息
                if (shareGroupService.insert(shareGroup).isSuccess()) {
                    log.info("{} insert 创建共享组信息 入参0:{}", CLASS_NAME, JSON.toJSON(shareGroup));

                    Activity activity = new Activity();
                    activity.setResourceType(RESOURCE_TYPE_OPPORTUNITY.getCode());
                    activity.setResourceId(opportunity.getOpportunityId());
                    activity.setActivityType(ACTIVITY_TYPE_SYSTEM_TRACE.getCode());
                    activity.setContent("创建了业务机会");
                    activity.setCreateBy(opportunity.getCreateBy());

                    // 创建动态信息
                    if (activityService.insert(activity).isSuccess()) {
                        log.info("{} insert 创建动态信息 入参0:{}", CLASS_NAME, JSON.toJSON(activity));
                        return new Result(true);
                    } else {
                        log.warn("{} insert 创建动态信息失败 入参0:{}", CLASS_NAME, JSON.toJSON(activity));
                        throw new BusinessException("创建动态信息失败");
                    }
                } else {
                    log.warn("{} insert 创建共享组信息失败 入参0:{}", CLASS_NAME, JSON.toJSON(shareGroup));
                    throw new BusinessException("创建共享组信息失败");
                }
            } else {
                log.warn("{} insert 创建业务机会信息失败 入参0:{}", CLASS_NAME, JSON.toJSON(opportunity));
                throw new BusinessException("创建业务机会信息失败");
            }

        } catch (Exception e) {
            log.warn("{} insert 创建业务机会异常 入参0:{}", CLASS_NAME, JSON.toJSON(opportunity));
            log.error(e.getMessage(), e);
            throw new BusinessException("新增业务机会失败");
        }
    }

    @Override
    public PageInfo<Opportunity> find(QueryOpportunityVO vo) {

        try {
            // 构造查询条件 如果不是禁用分页 设置分页信息
            if (StringUtils.isEmpty(vo.getDisablePaging()) || !vo.getDisablePaging()) {
                PageHelper.startPage(vo.getPageNum(), vo.getPageSize());
            }
            // 设置关键字信息 模糊查询
            vo.setWord(!StringUtils.isEmpty(vo.getWord()) ? "%".concat(vo.getWord()).concat("%") : null);

            // 查询
            List<Opportunity> opportunityList = opportunityMapper.find(vo);
            log.info("{} find 分页查询机会信息 入参0:{}, 结果0:{}", CLASS_NAME, JSON.toJSON(vo), JSON.toJSON(opportunityList));

            return new PageInfo<>(opportunityList);
        } catch (Exception e) {
            log.warn("{} find 分页查询机会信息异常 入参0:{}", CLASS_NAME, JSON.toJSON(vo));
            log.error(e.getMessage(), e);
            return new PageInfo<>(new ArrayList<>());
        }
    }

    @Override
    public Opportunity findById(Integer opportunityId) {

        try {

            // 根据Id查询业务机会详情
            Opportunity opportunity = opportunityMapper.findById(opportunityId);
            log.info("{} findById 根据Id查询业务机会详情 入参0:{}, 结果0:{}", CLASS_NAME, opportunityId, JSON.toJSON(opportunity));

            return opportunity;
        } catch (Exception e) {
            log.warn("{} findById 根据Id查询业务机会详情异常 入参0:{}", CLASS_NAME, opportunityId);
            log.error(e.getMessage(), e);
            return new Opportunity();
        }
    }

    @Override
    @Transactional(rollbackFor = {BusinessException.class}, propagation = Propagation.REQUIRED)
    public Result update(Opportunity opportunity) {

        try {

            // 如果为关闭阶段 判断是否为赢单
            if (OPPORTUNITY_PHASE_ON.getCode().equals(opportunity.getPhase())) {
                opportunity.setCloseDate(new Date());
                opportunity.setLossReason(opportunity.getWin() ? null : opportunity.getLossReason());
            } else {
                opportunity.setWin(null);
                opportunity.setLossReason(null);
                opportunity.setCloseDate(null);
            }
            // 更新/修改业务机会
            boolean result = opportunityMapper.update(opportunity) > 0;
            log.info("{} update 更新/修改业务机会 入参0:{} 结果0:{}", CLASS_NAME, JSON.toJSON(opportunity), result);

            return new Result(result);
        } catch (Exception e) {
            log.warn("{} update 更新/修改业务机会异常 入参0:{}", CLASS_NAME, JSON.toJSON(opportunity));
            log.error(e.getMessage(), e);
            throw new BusinessException("更新/修改业务机会失败");
        }
    }

    @Override
    @Transactional(rollbackFor = {BusinessException.class}, propagation = Propagation.REQUIRED)
    public Result insertContactsRole(ContactsRole contactsRole) {

        try {

            // 设置参数类型
            contactsRole.setRole(CONTACTS_ROLE_TYPE_LIAISONS.getCode());
            // 添加联系人信息
            boolean result = opportunityMapper.insertContactsRole(contactsRole) > 0;
            log.info("{} insertContactsRole 添加联系人信息 入参0:{} 结果0:{}", CLASS_NAME, JSON.toJSON(contactsRole), result);

            return new Result(result);
        } catch (Exception e) {
            log.warn("{} insertContactsRole 添加联系人信息异常 入参0:{}", CLASS_NAME, JSON.toJSON(contactsRole));
            log.error(e.getMessage(), e);
            throw new BusinessException("添加联系人信息失败");
        }
    }

    @Override
    @Transactional(rollbackFor = {BusinessException.class}, propagation = Propagation.REQUIRED)
    public Result updateContactsRole(ContactsRole contactsRole) {

        try {

            // 修改联系人角色信息
            boolean result = opportunityMapper.updateContactsRole(contactsRole) > 0;
            log.info("{} updateContactsRole 修改联系人角色信息 入参0:{} 结果0:{}", CLASS_NAME, JSON.toJSON(contactsRole), result);

            return new Result(result);
        } catch (Exception e) {
            log.info("{} updateContactsRole 修改联系人角色信息异常 入参0:{}", CLASS_NAME, JSON.toJSON(contactsRole));
            log.warn(e.getMessage(), e);
            throw new BusinessException("修改联系人角色信息异常");
        }
    }

    @Override
    @Transactional(rollbackFor = {BusinessException.class}, propagation = Propagation.REQUIRED)
    public Result deleteContactsRole(ContactsRole contactsRole) {

        try {

            // 移除联系人角色
            boolean result = opportunityMapper.deleteContactsRole(contactsRole) > 0;
            log.info("{} deleteContactsRole 移除联系人角色 入参0:{} 结果0:{}", CLASS_NAME, JSON.toJSON(contactsRole), result);

            return new Result(result);
        } catch (Exception e) {
            log.info("{} deleteContactsRole 移除联系人角色异常 入参0:{}", CLASS_NAME, JSON.toJSON(contactsRole));
            log.warn(e.getMessage(), e);
            throw new BusinessException("删除联系人失败");
        }
    }

    @Override
    @Transactional(rollbackFor = {BusinessException.class}, propagation = Propagation.REQUIRED)
    public Result delete(Opportunity opportunity) {

        try {

            // 资源组
            ShareGroup shareGroup = new ShareGroup();
            shareGroup.setResourceType(RESOURCE_TYPE_OPPORTUNITY.getCode());
            shareGroup.setResourceId(opportunity.getOpportunityId());
            // 删除资源组
            Result deleteShareGroup = shareGroupService.deleteByResource(shareGroup);
            log.info("{} delete 删除资源组 入参0:{} 结果0:{}", CLASS_NAME, JSON.toJSON(opportunity), JSON.toJSON(deleteShareGroup));
            if (!deleteShareGroup.isSuccess()) {
                throw new BusinessException("删除资源组失败");
            }

            // 动态
            Activity activity = new Activity();
            activity.setResourceType(RESOURCE_TYPE_OPPORTUNITY.getCode());
            activity.setResourceId(opportunity.getOpportunityId());
            // 删除动态
            Result deleteActivity = activityService.deleteByResource(activity);
            log.info("{} delete 删除动态 入参0:{} 结果0:{}", CLASS_NAME, JSON.toJSON(opportunity), JSON.toJSON(deleteActivity));
            if (!deleteActivity.isSuccess()) {
                throw new BusinessException("删除动态失败");
            }

            boolean result = opportunityMapper.delete(opportunity) > 0;
            log.info("{} delete 删除业务机会 入参0:{} 结果0:{}", CLASS_NAME, JSON.toJSON(opportunity), result);

            return new Result(result);

        } catch (Exception e) {
            log.warn("{} delete 删除业务机会异常 入参0:{}", CLASS_NAME, JSON.toJSON(opportunity));
            log.warn(e.getMessage(), e);
            throw new BusinessException("删除业务机会失败");
        }
    }

    @Override
    public List<Map<String, Integer>> findMonthlyFunnel(QueryOpportunityVO vo) {

        try {
            // 设置阶段信息
            vo.setPhaseList(getPhaseCodeList());
            // 设置时间信息
            vo.setStartCreateDate(DateUtil.firstDayInMonth());
            vo.setEndCreateDate(DateUtil.lastDayInMonth());
            // 查询本月我参与的业务机会
            List<Map<String, Integer>> monthlyFunnel = opportunityMapper.findMonthlyFunnel(vo);
            log.info("{} findMonthlyFunnel 查询本月我参与的业务机会 入参0:{} 结果0:{}", CLASS_NAME, JSON.toJSON(vo), JSON.toJSON(monthlyFunnel));

            return monthlyFunnel;
        } catch (Exception e) {
            log.warn("{} findMonthlyFunnel 查询本月我参与的业务机会异常 入参0:{}", CLASS_NAME, JSON.toJSON(vo));
            log.error(e.getMessage(), e);
            return new ArrayList<>();
        }
    }

    @Override
    public List<Map<String, Integer>> findMonthlyConversion(QueryOpportunityVO vo) {

        try {
            // 设置时间信息
            vo.setStartCreateDate(DateUtil.firstDayInMonth());
            vo.setEndCreateDate(DateUtil.lastDayInMonth());
            // 查询本月我的转化情况
            List<Map<String, Integer>> monthlyConversion = opportunityMapper.findMonthlyConversion(vo);
            log.info("{} findMonthlyConversion 查询本月我的转化情况 入参0:{} 结果0:{}", CLASS_NAME, JSON.toJSON(vo), JSON.toJSON(monthlyConversion));

            return monthlyConversion;
        } catch (Exception e) {
            log.warn("{} findMonthlyConversion 查询本月我的转化情况异常 入参0:{}", CLASS_NAME, JSON.toJSON(vo));
            log.error(e.getMessage(), e);
            return new ArrayList<>();
        }
    }

    @Override
    public List<Opportunity> findRecentlyClosing(QueryOpportunityVO vo) {

        try {
            // 得到阶段列表, 排除关闭的阶段
            vo.setPhaseList(getPhaseCodeList(Byte.parseByte("5")));
            // 设置时间为最近一周
            vo.setEndDate(DateUtil.toEndDate(DateUtil.addDays(new Date(), 7)));
            // 查询将要结束的业务机会(最近一周没有关闭的业务机会)
            List<Opportunity> recentlyClosing = opportunityMapper.findRecentlyClosing(vo);
            log.info("{} findRecentlyClosing 查询将要结束的业务机会 入参0:{} 结果0:{}", CLASS_NAME, JSON.toJSON(vo), JSON.toJSON(recentlyClosing));

            return recentlyClosing;
        } catch (Exception e) {
            log.warn("{} findRecentlyClosing 查询将要结束的业务机会异常 入参0:{}", CLASS_NAME, JSON.toJSON(vo));
            log.error(e.getMessage(), e);
            return new ArrayList<>();
        }
    }
}
